//--------------------Sonic CD Water Script-------------------//
//--------Scripted by Christian Whitehead 'The Taxman'--------//
//-------Unpacked By Rubberduckycooly's Script Unpacker-------//

// Aliases
#alias Object.Value0			:	Object.FrameTimer
#alias Object.Value1			:	Object.ConstBubbleTimer
#alias Object.Value2			:	Object.RandBubbleTimer
#alias Object.Value3			:	Object.Unused

// Bubble Aliases
#alias Object.Value1			:	Object.Angle
#alias Object.Value2			:	Object.XVelocity
#alias Object.Value3			:	Object.YVelocity

#alias Player.Value4			:	Player.SpeedShoes  //Drowning ME

// HUD alias
#alias Object[24].PropertyValue	:	HUD.CurrentTimePeriod

// States
#alias 0	:	WATER_CREATEBUBBLE_1
#alias 1	:	WATER_CREATEBUBBLE_2
#alias 2	:	WATER_CREATEBUBBLE_3
#alias 3	:	WATER_CREATE_COUNT_BUBBLE_1
#alias 4	:	WATER_CREATE_COUNT_BUBBLE_2
#alias 5	:	WATER_CREATE_COUNT_BUBBLE_3
#alias 6	:	WATER_CREATE_COUNT_BUBBLE_4
#alias 7	:	WATER_CREATE_COUNT_BUBBLE_5
#alias 8	:	WATER_CREATE_COUNT_BUBBLE_6
#alias 9	:	WATER_DROWNING
#alias 10	:	WATER_DROWNED

// Player List Pos Aliases
#alias 0	:	PLAYER_SONIC_A
#alias 1	:	PLAYER_TAILS_A
#alias 2	:	PLAYER_KNUCKLES
#alias 3	:	PLAYER_AMY

// Priority
#alias 1	:	PRIORITY_ACTIVE

// Ink Effects
#alias 2	:	INK_ALPHA

// Global SFX
#alias 24	:	SFX_G_FLYING
#alias 25	:	SFX_G_TIRED

// Global BGMs
#alias 7	:	TRACK_DROWNING

// Stage SFX
#alias 0	:	SFX_S_WATERSPLASH
#alias 7	:	SFX_S_DROWNING
#alias 11	:	SFX_S_AIRALERT //This MUST be 11 for Drowning ME, it's intentional -Sara
#alias 10	:	SFX_S_DROWNALERT

// Time Periods
#alias 0	:	TIME_PRESENT
#alias 1	:	TIME_PAST
#alias 2	:	TIME_GOOD_FUTURE
#alias 3	:	TIME_BAD_FUTURE

// Air Bubble Property Values
#alias 2	:	BUBBLE_SMALL

// Shields
#alias 3	:	SHIELD_BUBBLE

// Function declarations
#function Water_CreateAirBubble
#function Water_CreateCountBubble

function Water_CreateAirBubble
	if Object.ConstBubbleTimer > 0
		Object.ConstBubbleTimer--
		if Object.RandBubbleTimer > 0
			Object.RandBubbleTimer--
		else
			if Player.Shield != SHIELD_BUBBLE
				CreateTempObject(TypeName[Air Bubble], BUBBLE_SMALL, Player.XPos, Player.YPos)
			end if
			Object[TempObjectPos].DrawOrder = 4

			Object[TempObjectPos].YVelocity = -0x8800
			if Player.Direction == FACING_RIGHT
				Object[TempObjectPos].XPos += 0x60000
			else
				Object[TempObjectPos].XPos -= 0x60000
				Object[TempObjectPos].Angle = 256
			end if
			Object[TempObjectPos].XVelocity = Object[TempObjectPos].XPos
			Object.RandBubbleTimer = 512
		end if
	else
		Rand(TempValue0, 3)
		if TempValue0 == 1
			Rand(Object.RandBubbleTimer, 16)
			Object.RandBubbleTimer += 8
		else
			Object.RandBubbleTimer  = 512
		end if

		Object.ConstBubbleTimer = 60
		if Player.Shield != SHIELD_BUBBLE
			CreateTempObject(TypeName[Air Bubble], BUBBLE_SMALL, Player.XPos, Player.YPos)
		end if
		Object[TempObjectPos].DrawOrder = 4

		Object[TempObjectPos].YVelocity = -0x8800
		if Player.Direction == FACING_RIGHT
			Object[TempObjectPos].XPos += 0x60000
		else
			Object[TempObjectPos].XPos -= 0x60000
			Object[TempObjectPos].Angle = 256
		end if
		Object[TempObjectPos].XVelocity = Object[TempObjectPos].XPos
	end if
end function


function Water_CreateCountBubble
	CreateTempObject(TypeName[Countdown Bubble], TempValue0, Player.XPos, Player.YPos)
	Object[TempObjectPos].DrawOrder = 4

	Object[TempObjectPos].YVelocity = -0x8800
	if Player.Direction == FACING_RIGHT
		Object[TempObjectPos].XPos += 0x60000
	else
		Object[TempObjectPos].XPos -= 0x60000
		Object[TempObjectPos].Angle = 256
	end if
	Object[TempObjectPos].XVelocity = Object[TempObjectPos].XPos
end function


sub ObjectMain
	Player.WaterStream = 0
	if Object.YPos < Stage.NewWaterLevel
		Object.YPos += 0x10000
	end if
	if Object.YPos > Stage.NewWaterLevel
		Object.YPos -= 0x10000
	end if

	TempValue0   = Oscillation
	TempValue0 <<= 2
	Sin(Stage.WaterLevel, TempValue0)
	Stage.WaterLevel <<= 9
	Stage.WaterLevel  += Object.YPos

	// If the player about to enter the water
	if Player.GravityStrength == 0x3800
		if Player.YPos > Object.YPos
			if Player.State != Player_State_Death
				Player.YVelocity >>= 2
				if Object.YPos < Stage.NewWaterLevel
					Player.YVelocity += 0x10000
				end if
				if Player.State == Player_State_Fly
					StopSFX(SFX_G_FLYING)
					StopSFX(SFX_G_TIRED)
				end if
				Player.XVelocity >>= 1

				Player.Speed 	 >>= 1
				Player.TopSpeed  >>= 1
				
				Player.Acceleration >>= 1
				Player.Deceleration >>= 1

				Player.AirAcceleration >>= 1
				Player.AirDeceleration >>= 1

				Player.GravityStrength  =  0x1000
				Player.JumpStrength		=  0x38000
#platform: Use_Origins
					if Stage.PlayerListPos == PLAYER_KNUCKLES
						Player.JumpStrength = 0x2B9B0
					end if
#endplatform
				Player.JumpCap			= -0x20000

				CreateTempObject(TypeName[Water Splash], 0, Player.XPos, Stage.WaterLevel)
				Object[TempObjectPos].DrawOrder = 4
				PlayStageSfx(SFX_S_WATERSPLASH, false)
				Object.ConstBubbleTimer = 52
				Player.AirTimer = 0
				//Drowning ME
				if Music.CurrentTrack==TRACK_DROWNING
					if Object[2].Type==TypeName[Invincibility]
						PlayMusic(2)
					else
						if Player.SpeedShoes>0
							PlayMusic(3)
						else
							if Stage.ActNo! = 3
								PlayMusic(0)
							else
								PlayMusic(4)
							end if
						end if
					end if				
				end if
			end if
		end if
	else
		if Player.AirTimer == 0
			Object.State = WATER_CREATEBUBBLE_1
		end if

		switch Object.State
		case WATER_CREATEBUBBLE_1
			CallFunction(Water_CreateAirBubble)
			Player.AirTimer++
			if Player.AirTimer == 360
				PlayStageSfx(SFX_S_AIRALERT, false) // Drowning ME -- Always this one -Sara
				Object.State++
			end if
			//Drowning ME
			if Music.CurrentTrack==TRACK_DROWNING
				if Object[2].Type==TypeName[Invincibility]
					PlayMusic(2)
				else
					if Player.SpeedShoes>0
						PlayMusic(3)
					else
						if Stage.ActNo! = 3
							PlayMusic(0)
						else
							PlayMusic(4)
						end if
					end if
				end if
			end if
			break

		case WATER_CREATEBUBBLE_2
			CallFunction(Water_CreateAirBubble)
			Player.AirTimer++
			if Player.AirTimer == 660
				PlayStageSfx(SFX_S_AIRALERT, false) // Drowning ME -- Always this one -Sara
				Object.State++
			end if
			break
			
		case WATER_CREATEBUBBLE_3
			CallFunction(Water_CreateAirBubble)
			Player.AirTimer++
			if Player.AirTimer == 960
				PlayStageSfx(SFX_S_AIRALERT, false) // Drowning ME -- Always this one -Sara
				Object.State++
			end if
			break

		case WATER_CREATE_COUNT_BUBBLE_1
			CallFunction(Water_CreateAirBubble)
			Player.AirTimer++
			if Player.AirTimer == 1080
				PlayMusic(TRACK_DROWNING) //Drowning ME
				TempValue0 = 0
				CallFunction(Water_CreateCountBubble)
				Object.State++
			end if
			break

		case WATER_CREATE_COUNT_BUBBLE_2
			TempValue0 = Player.AirTimer
			TempValue0 &= 63
			if TempValue0 == 0
				PlayStageSfx(10, 0)
			end if
			Player.AirTimer++
			if Player.AirTimer == 1200
				TempValue0 = 1
				CallFunction(Water_CreateCountBubble)
				Object.State++
			end if
			break

		case WATER_CREATE_COUNT_BUBBLE_3
			CallFunction(Water_CreateAirBubble)
			TempValue0 = Player.AirTimer
			TempValue0 &= 63
			if TempValue0 == 0
				PlayStageSfx(10, 0)
			end if
			Player.AirTimer++
			if Player.AirTimer == 1320
				TempValue0 = 2
				CallFunction(Water_CreateCountBubble)
				Object.State++
			end if
			break

		case WATER_CREATE_COUNT_BUBBLE_4
			CallFunction(Water_CreateAirBubble)
			TempValue0  = Player.AirTimer
			TempValue0 &= 63
			if TempValue0 == 0
				PlayStageSfx(SFX_S_DROWNALERT, false)
			end if

			Player.AirTimer++
			if Player.AirTimer == 1440
				TempValue0 = 3
				CallFunction(Water_CreateCountBubble)
				Object.State++
			end if
			break

		case WATER_CREATE_COUNT_BUBBLE_5
			CallFunction(Water_CreateAirBubble)
			TempValue0  = Player.AirTimer
			TempValue0 &= 63
			if TempValue0 == 0
				PlayStageSfx(SFX_S_DROWNALERT, false)
			end if

			Player.AirTimer++
			if Player.AirTimer == 1560
				TempValue0 = 4
				CallFunction(Water_CreateCountBubble)
				Object.State++
			end if
			break

		case WATER_CREATE_COUNT_BUBBLE_6
			CallFunction(Water_CreateAirBubble)
			TempValue0  = Player.AirTimer
			TempValue0 &= 63
			if TempValue0 == 0
				PlayStageSfx(SFX_S_DROWNALERT, false)
			end if

			Player.AirTimer++
			if Player.AirTimer == 1680
				TempValue0 = 5
				CallFunction(Water_CreateCountBubble)
				Object.State++
			end if
			break

		case WATER_DROWNING
			CallFunction(Water_CreateAirBubble)
			Player.AirTimer++
			if Player.AirTimer == 1800
				if Player.State != Player_State_Death
					Stage.TimeEnabled = false
					Screen.CameraEnabled = false
					Player.State = Player_State_Drown
					Player.Animation = ANI_DROWNING

					Player.Speed	 = 0
					Player.XVelocity = 0
					Player.YVelocity = 0

					Player.TileCollisions = false
					Player.ObjectInteraction = false
					Player.DrawOrder = 5
					Object.ConstBubbleTimer = 2
					Object.Unused = 60	// ?
					PlayStageSfx(SFX_S_DROWNING, false)

					Object.State++
				end if
			end if
			break

		case WATER_DROWNED
			Player.AirTimer++
			if Player.AirTimer == 1860
				Object.State++
			end if
			if Object.ConstBubbleTimer > 0
				Object.ConstBubbleTimer--
				if Object.RandBubbleTimer > 0
					Object.RandBubbleTimer--
				else
					Rand(TempValue1, 2)
					TempValue1 += 2
					CreateTempObject(TypeName[Air Bubble], TempValue1, Player.XPos, Player.YPos)
					Object[TempObjectPos].DrawOrder = 5
					Object[TempObjectPos].YVelocity = -0x8800
					Object[TempObjectPos].YPos -= 0x60000
					Rand(Object[TempObjectPos].Angle, 256)
					Object[TempObjectPos].XVelocity = Object[TempObjectPos].XPos
					Object.RandBubbleTimer = 512
				end if
			else
				Rand(TempValue0, 4)
				if TempValue0 == 1
					Object.RandBubbleTimer = 2
				else
					Object.RandBubbleTimer = 512
				end if
				Object.ConstBubbleTimer = 6
				Rand(TempValue1, 2)
				TempValue1 += 2
				CreateTempObject(TypeName[Air Bubble], TempValue1, Player.XPos, Player.YPos)
				Object[TempObjectPos].DrawOrder = 5
				Object[TempObjectPos].YVelocity = -0x8800
				Object[TempObjectPos].YPos -= 0x60000
				Rand(Object[TempObjectPos].Angle, 256)
				Object[TempObjectPos].XVelocity = Object[TempObjectPos].XPos
			end if
			break

		end switch

		// Restore physics when exiting water
		if Player.YPos < Object.YPos
			if Player.State != Player_State_Death
				Player.YVelocity <<= 1
				if Player.YVelocity < -0x100000
					Player.YVelocity = -0x100000
				end if

				if Player.State == Player_State_Fly
					if Player.Timer < 480
						PlaySfx(SFX_G_FLYING, true)
					else
						PlaySfx(SFX_G_TIRED, true)
					end if
				end if

				Player.TopSpeed = 0x60000

				Player.Acceleration = 0xC00
				Player.Deceleration = 0xC00
				
				Player.AirAcceleration = 0x1800
				Player.AirDeceleration = 0x600

				Player.GravityStrength	= 0x3800
				
				Player.JumpStrength		=  0x68000

#platform: Use_Origins
					if Stage.PlayerListPos == PLAYER_KNUCKLES
						Player.JumpStrength = 0x5B9B0
					end if
#endplatform

				Player.JumpCap			= -0x40000

				CreateTempObject(TypeName[Water Splash], 0, Player.XPos, Stage.WaterLevel)
				Object[TempObjectPos].DrawOrder = 4
				PlayStageSfx(SFX_S_WATERSPLASH, false)
				Player.AirTimer = 0
				//Drowning ME
				if Music.CurrentTrack==TRACK_DROWNING
					if Object[2].Type==TypeName[Invincibility]
						PlayMusic(2)
					else
						if Player.SpeedShoes>0
							PlayMusic(3)
						else
							if Stage.ActNo! = 3
								PlayMusic(0)
							else
								PlayMusic(4)
							end if
						end if
					end if
				end if
			end if
		end if
	end if
	Stage.WaterLevel >>= 16
end sub


sub ObjectDraw
	Object.FrameTimer++
	if Object.FrameTimer > 23
		Object.FrameTimer = 0
		Object.Frame++
		Object.Frame &= 3
	end if

	TempValue0   = Screen.XOffset
	Sin(TempValue1, Oscillation)
	TempValue1 >>= 5

	TempValue0 += TempValue1
	TempValue0 &= 63
	FlipSign(TempValue0)

	TempValue1  = Stage.WaterLevel
	TempValue1 -= Screen.YOffset
	DrawSpriteScreenFX(Object.Frame, FX_INK, TempValue0, TempValue1)

	TempValue0 += 128
	DrawSpriteScreenFX(Object.Frame, FX_INK, TempValue0, TempValue1)

	TempValue0 += 128
	DrawSpriteScreenFX(Object.Frame, FX_INK, TempValue0, TempValue1)

	TempValue0 += 128
	DrawSpriteScreenFX(Object.Frame, FX_INK, TempValue0, TempValue1)
end sub


sub ObjectStartup
	LoadSpriteSheet("R4/Objects.gif")
	Player.AirTimer = 0
	TempValue7 = -1
	switch Stage.ActNo
	case 1
		switch HUD.CurrentTimePeriod
		case TIME_PRESENT
			if Player.XPos > 0x5E00000
				TempValue7 = 0x2640000
			end if
			break
		case TIME_GOOD_FUTURE
		case TIME_BAD_FUTURE
			if Player.XPos > 0x9100000
				TempValue7 = 0x1100000
			end if
			break
			
		end switch
		break

	case 2
		switch HUD.CurrentTimePeriod
		case TIME_PRESENT
			if Player.XPos > 0x4B00000
				TempValue7 = 0x5340000
			end if
			if Player.XPos > 0xC200000
				TempValue7 = 0x7800000
			end if
			if Player.XPos > 0x13300000
				TempValue7 = 0x5000000
			end if
			break

		case TIME_GOOD_FUTURE
		case TIME_BAD_FUTURE
			if Player.XPos > 0x4B00000
				TempValue7 = 0x5100000
			end if
			if Player.XPos > 0x4100000
				TempValue7 = 0x3900000
			end if
			// why is this repeated? no clue
			if Player.XPos > 0x4100000
				TempValue7 = 0x3900000
			end if
			break

		end switch

		break
	end switch

	ArrayPos0 = 32
	while ArrayPos0 < 1056
		if Object[ArrayPos0].Type == TypeName[Water]
			Object[ArrayPos0].Priority  = PRIORITY_ACTIVE
			Object[ArrayPos0].DrawOrder = 5
			Object[ArrayPos0].InkEffect = INK_ALPHA
			Object[ArrayPos0].Alpha		= 160
			if TempValue7 == -1
				Stage.NewWaterLevel = Object[ArrayPos0].YPos
			else
				Stage.NewWaterLevel = TempValue7
				Object[ArrayPos0].YPos = TempValue7
			end if
			if Player.YPos > Stage.NewWaterLevel
				Player.YVelocity >>= 2
				Player.XVelocity >>= 1

				Player.Speed 	>>= 1
				Player.TopSpeed >>= 1

				Player.Acceleration >>= 1
				Player.Deceleration >>= 1

				Player.AirAcceleration >>= 1
				Player.AirDeceleration >>= 1

				Player.GravityStrength  = 0x1000
				
				// Bug Details:
				// The line below doesn't check for Knuckles, prolly should though
				// So if Knuckles starts a scene underwater (whether it be with a checkpoint, time travelling, or anything), he'll have Sonic's jump height
				Player.JumpStrength		= 0x38000

				if game.hasPlusDLC == true
					if Stage.PlayerListPos == PLAYER_KNUCKLES
						Player.JumpStrength = 0x2B9B0
					end if
				end if

				Object.ConstBubbleTimer = 52
			end if
		end if
		ArrayPos0++
	loop

	SpriteFrame(0, -8, 128, 16, 1, 1)	// #0 - Water Waves frame 0
	SpriteFrame(0, -8, 128, 16, 1, 18)	// #1 - Water Waves frame 1
	SpriteFrame(0, -8, 128, 16, 1, 35)	// #2 - Water Waves frame 2
	SpriteFrame(0, -8, 128, 16, 1, 52)	// #3 - Water Waves frame 3
end sub


// ========================
// Editor Subs
// ========================

sub RSDKDraw
	TempValue0   = Object.XPos

	DrawSpriteXY(0, TempValue0, Object.YPos)
	TempValue0 += 0x800000
	DrawSpriteXY(0, TempValue0, Object.YPos)
	TempValue0 += 0x800000
	DrawSpriteXY(0, TempValue0, Object.YPos)
	TempValue0 += 0x800000
	DrawSpriteXY(0, TempValue0, Object.YPos)
	TempValue0 += 0x800000
end sub


sub RSDKLoad
	LoadSpriteSheet("R4/Objects.gif")
	SpriteFrame(0, -8, 128, 16, 1, 1)	// #0 - Water Waves frame 0
	SpriteFrame(0, -8, 128, 16, 1, 18)	// #1 - Water Waves frame 1
	SpriteFrame(0, -8, 128, 16, 1, 35)	// #2 - Water Waves frame 2
	SpriteFrame(0, -8, 128, 16, 1, 52)	// #3 - Water Waves frame 3

	SetVariableAlias(ALIAS_VAR_PROPVAL, "unused")
end sub
